#version 330

#define DEBUG

out vec3 out_Color;

uniform sampler2D u_depthTX;
uniform sampler2D u_normalTX;
uniform sampler2D u_diffuseTX;
uniform sampler2D u_miscTX;

uniform float u_Near;
uniform float u_Far;

uniform vec3 u_Up;

uniform vec3 u_bottomColor;
uniform vec3 u_topColor;

uniform int u_gbufferView;

in vec2 fs_Texcoord;

const float ambientFactor = .1f;

// Code from : http://aras-p.info/texts/CompactNormalStorage.html
vec3 unpackNormal(vec2 encNorm) {
#ifdef DEBUG
	if(encNorm.x < .000001f && encNorm.y < .00000001)
		return vec3(.0f, .0f, .0f);
#endif

	vec2 fenc = encNorm*4.0f - 2.0f;
	float f = dot(fenc, fenc);
	float g = sqrt(1.0f -.25f*f);
	return vec3(fenc*g,1.0f - .5f*f);
}

// Packing and unpacking code courtesy of:
// http://www.ozone3d.net/blogs/lab/20080604/glsl-float-to-rgba8-encoder/
// http://olivers.posterous.com/linear-depth-in-glsl-for-real

vec4 packFloatTo4x8(in float val) {
	const vec4 bitSh = vec4(256.0f*256.0f*256.0f, 256.0f*256.0f, 256.0f, 1.0f);
	const vec4 bitMsk = vec4(0.0f, 1.0f/256.0f, 1.0f/256.0f, 1.0f/256.0f);
	vec4 result = fract(val * bitSh);
	result -= result.xxyz * bitMsk;
	return result;
}

vec4 pack2FloatTo4x8(in vec2 val) {
	const vec2 bitSh = vec2(256.0f, 1.0f);
	const vec2 bitMsk = vec2(0.0f, 1.0f/256.0f);
	vec2 res1 = fract(val.x * bitSh);
	res1 -= res1.xx * bitMsk;
	vec2 res2 = fract(val.y * bitSh);
	res2 -= res2.xx * bitMsk;
	return vec4(res1.x,res1.y,res2.x,res2.y);
}

float unpack4x8ToFloat(in vec4 val) {
	const vec4 unshift = vec4(1.0f/(256.0f*256.0f*256.0f), 1.0f/(256.0f*256.0f), 1.0f/256.0f, 1.0f);
	return dot(val, unshift);
}

vec2 unpack4x8To2Float(in vec4 val) {
	const vec2 unshift = vec2(1.0f/256.0f, 1.0f);
	return vec2(dot(val.xy, unshift), dot(val.zw, unshift));
}

float linearizeDepth(float exp_depth, float near, float far) {
    return	(2 * near) / (far + near -  exp_depth * (far - near)); 
}

void main(void) {

	vec3 light = mix(u_bottomColor, u_topColor, (.5f + .5f*dot(unpackNormal(unpack4x8To2Float(texture(u_normalTX, fs_Texcoord))), u_Up)));

	out_Color = texture(u_diffuseTX, fs_Texcoord).rgb*light*ambientFactor;
}